#include "NameLayer.h"
#include "ConstClass.h"
#include "StartLayer.h"
#include "AudioManage.h"

#define FONT_NAME  "fonts/Thonburi.ttf"
#define FONT_SIZE  36
#define PNG_TYPE_YOUR_NAME "Start/type_your_name.png"
#define PNG_OK "Tip/ok.png"
#define PNG_CANCEL "Tip/cancel.png"

NameLayer::NameLayer()
{
}


NameLayer::~NameLayer()
{
}

static Rect getRect(Node * node)
{
	Rect rc;
	rc.origin = node->getPosition();
	rc.size = node->getContentSize();
	rc.origin.x -= rc.size.width / 2;
	rc.origin.y -= rc.size.height / 2;
	return rc;
}

bool NameLayer::init()
{
	Layer::init();

	LayerColor* layerColor = LayerColor::create(cocos2d::Color4B(0, 0, 0, 200));

	this->addChild(layerColor, 5);

	auto s = Director::getInstance()->getWinSize();
	Sprite* typeMark = Sprite::create(PNG_TYPE_YOUR_NAME);
	typeMark->setPosition(Vec2(s.width * 0.5f, s.height * 0.8f));

	this->addChild(typeMark, 6);

	MenuItemImage* okItem = MenuItemImage::create(PNG_OK, PNG_OK, CC_CALLBACK_0(NameLayer::typeOK, this));
	okItem->setPosition(Vec2(s.width * 0.6f, s.height * 0.4f));
	MenuItemImage* cancelItem = MenuItemImage::create(PNG_CANCEL, PNG_CANCEL, CC_CALLBACK_0(NameLayer::typeCancel, this));
	cancelItem->setPosition(Vec2(s.width * 0.8f, s.height * 0.4f));

	Menu* startMenu = Menu::create(okItem, cancelItem, NULL);
	startMenu->setPosition(Vec2::ZERO);

	this->addChild(startMenu, 6);

	return true;
}

void NameLayer::onEnter()
{
	Layer::onEnter();

	_charLimit = 6;

	_textFieldAction = RepeatForever::create(
		Sequence::create(
		FadeOut::create(0.25),
		FadeIn::create(0.25),
		nullptr
		));
	_textFieldAction->retain();
	_action = false;

	Size size = Director::getInstance()->getVisibleSize();
	auto s = Director::getInstance()->getWinSize();

	string name;
	if ("" == ConstClass::MY_NAME)
	{
		name = "<your name>";
	}
	else
	{
		name = "<your name>";
		this->myName = ConstClass::MY_NAME;
	}

	_textField = TextFieldTTF::textFieldWithPlaceHolder(name,
		FONT_NAME,
		FONT_SIZE);
	//_textField->setColor(cocos2d::Color3B(255, 255, 255));
	_textField->setPosition(Vec2(s.width * 0.5f, s.height * 0.6f));
	this->addChild(_textField, 6);

	_textField->setDelegate(this);
	_trackNode = _textField;

	auto listener1 = EventListenerTouchOneByOne::create();
	listener1->setSwallowTouches(true);
	listener1->onTouchBegan = CC_CALLBACK_2(NameLayer::onTouchBegan, this);
	listener1->onTouchEnded = CC_CALLBACK_2(NameLayer::onTouchEnded, this);

	_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);
	m_listener = listener1;
}

void NameLayer::onExit()
{
	Layer::onExit();
	_textFieldAction->release();
}

void NameLayer::keyboardWillShow(cocos2d::IMEKeyboardNotificationInfo& info)
{
	CCLOG("TextInputTest:keyboardWillShowAt(origin:%f,%f, size:%f,%f)",
		info.end.origin.x, info.end.origin.y, info.end.size.width, info.end.size.height);

	if (!_trackNode)
	{
		return;
	}

	auto rectTracked = getRect(_trackNode);
	CCLOG("TextInputTest:trackingNodeAt(origin:%f,%f, size:%f,%f)",
		rectTracked.origin.x, rectTracked.origin.y, rectTracked.size.width, rectTracked.size.height);

	// if the keyboard area doesn't intersect with the tracking node area, nothing need to do.
	if (!rectTracked.intersectsRect(info.end))
	{
		return;
	}

	// assume keyboard at the bottom of screen, calculate the vertical adjustment.
	float adjustVert = info.end.getMaxY() - rectTracked.getMinY();
	CCLOG("TextInputTest:needAdjustVerticalPosition(%f)", adjustVert);

	// move all the children node of KeyboardNotificationLayer
	auto& children = getChildren();
	Node * node = 0;
	ssize_t count = children.size();
	Vec2 pos;
	for (int i = 0; i < count; ++i)
	{
		node = children.at(i);
		pos = node->getPosition();
		pos.y += adjustVert;
		node->setPosition(pos);
	}
}

bool NameLayer::onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event)
{
	CCLOG("++++++++++++++++++++++++++++++++++++++++++++");
	_beginPos = touch->getLocation();
	return true;
}

void NameLayer::onTouchEnded(cocos2d::Touch* touch, cocos2d::Event* event)
{
	if (!_trackNode)
	{
		return;
	}

	auto endPos = touch->getLocation();

	float delta = 5.0f;
	if (std::abs(endPos.x - _beginPos.x) > delta
		|| std::abs(endPos.y - _beginPos.y) > delta)
	{
		// not click
		_beginPos.x = _beginPos.y = -1;
		return;
	}

	// decide the trackNode is clicked.
	Rect rect;
	auto point = _trackNode->convertTouchToNodeSpace(touch);
	CCLOG("KeyboardNotificationLayer:clickedAt(%f,%f)", point.x, point.y);

	rect.size = _trackNode->getContentSize();
	CCLOG("KeyboardNotificationLayer:TrackNode at(origin:%f,%f, size:%f,%f)",
		rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);

	this->onClickTrackNode(rect.containsPoint(point));
	CCLOG("----------------------------------");
}

void  NameLayer::onClickTrackNode(bool bClicked)
{
	auto pTextField = (TextFieldTTF*)_trackNode;
	if (bClicked)
	{
		// TextFieldTTFTest be clicked
		CCLOG("TextFieldTTFDefaultTest:TextFieldTTF attachWithIME");
		pTextField->attachWithIME();
	}
	else
	{
		// TextFieldTTFTest not be clicked
		CCLOG("TextFieldTTFDefaultTest:TextFieldTTF detachWithIME");
		pTextField->detachWithIME();
	}
}

// TextFieldDelegate protocol
bool NameLayer::onTextFieldAttachWithIME(TextFieldTTF * sender)
{
	if (!_action)
	{
		_textField->runAction(_textFieldAction);
		_action = true;
	}
	return false;
}

bool NameLayer::onTextFieldDetachWithIME(TextFieldTTF * sender)
{
	if (_action)
	{
		_textField->stopAction(_textFieldAction);
		_textField->setOpacity(255);
		_action = false;
	}
	return false;
}

bool NameLayer::onTextFieldInsertText(TextFieldTTF * sender, const char * text, size_t nLen)
{
	// if insert enter, treat as default to detach with ime
	if ('\n' == *text)
	{
		return false;
	}

	// if the textfield's char count more than _charLimit, doesn't insert text anymore.
	if (sender->getCharCount() >= _charLimit)
	{
		return true;
	}

	// create a insert text sprite and do some action
	auto label = Label::createWithSystemFont(text, FONT_NAME, FONT_SIZE);
	this->addChild(label);
	Color3B color(226, 121, 7);
	label->setColor(color);

	// move the sprite from top to position
	auto endPos = sender->getPosition();
	if (sender->getCharCount())
	{
		endPos.x += sender->getContentSize().width / 2;
	}
	auto inputTextSize = label->getContentSize();
	Vec2 beginPos(endPos.x, Director::getInstance()->getWinSize().height - inputTextSize.height * 2);

	float duration = 0.5;
	label->setPosition(beginPos);
	label->setScale(8);

	auto seq = Sequence::create(
		Spawn::create(
		MoveTo::create(duration, endPos),
		ScaleTo::create(duration, 1),
		FadeOut::create(duration),
		nullptr),
		CallFuncN::create(CC_CALLBACK_1(NameLayer::callbackRemoveNodeWhenDidAction, this)),
		nullptr);
	label->runAction(seq);

	if (0 == sender->getCharCount())
	{
		this->myName = "";
	}

	this->myName.append(text);

	return false;
}

bool NameLayer::onTextFieldDeleteBackward(TextFieldTTF * sender, const char * delText, size_t nLen)
{
	// create a delete text sprite and do some action
	auto label = Label::createWithSystemFont(delText, FONT_NAME, FONT_SIZE);
	this->addChild(label);

	// move the sprite to fly out
	auto beginPos = sender->getPosition();
	auto textfieldSize = sender->getContentSize();
	auto labelSize = label->getContentSize();
	beginPos.x += (textfieldSize.width - labelSize.width) / 2.0f;

	auto winSize = Director::getInstance()->getWinSize();
	Vec2 endPos(-winSize.width / 4.0f, winSize.height * (0.5 + (float)rand() / (2.0f * RAND_MAX)));

	float duration = 1;
	float rotateDuration = 0.2f;
	int repeatTime = 5;
	label->setPosition(beginPos);

	auto seq = Sequence::create(
		Spawn::create(
		MoveTo::create(duration, endPos),
		Repeat::create(
		RotateBy::create(rotateDuration, (rand() % 2) ? 360 : -360),
		repeatTime),
		FadeOut::create(duration),
		nullptr),
		CallFuncN::create(CC_CALLBACK_1(NameLayer::callbackRemoveNodeWhenDidAction, this)),
		nullptr);
	label->runAction(seq);

	this->myName.pop_back();

	return false;
}

bool NameLayer::onDraw(TextFieldTTF * sender)
{
	return false;
}

void NameLayer::callbackRemoveNodeWhenDidAction(Node * node)
{
	this->removeChild(node, true);
}

void NameLayer::typeOK()
{
	AudioManage::button1Sound();

	ConstClass::MY_NAME = myName;

	UserDefault::sharedUserDefault()->setStringForKey("MyName", myName);

	this->onClickTrackNode(false);

	this->setVisible(false);
	_eventDispatcher->removeEventListener(m_listener);
}

void NameLayer::typeCancel()
{
	AudioManage::button2Sound();

	this->setVisible(false);
	_eventDispatcher->removeEventListener(m_listener);
}

void NameLayer::changeName()
{
	auto listener1 = EventListenerTouchOneByOne::create();
	listener1->setSwallowTouches(true);
	listener1->onTouchBegan = CC_CALLBACK_2(NameLayer::onTouchBegan, this);
	listener1->onTouchEnded = CC_CALLBACK_2(NameLayer::onTouchEnded, this);

	_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);
	m_listener = listener1;
}